package com.whq.common.loadclass;

import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Stack;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DynamicLoadClassPathUtil {
	private static final Logger LOGGER = LoggerFactory.getLogger(DynamicLoadClassPathUtil.class);
	
	/**
	 * 动态加载class目录 
	 * @param classRootPath
	 * class文件所在根路径 
	 * 例如/usr/java/classes下有一个test.App类，则/usr/java/classes即这个类的根路径，而.class文件的实际位置是/usr/java/classes/test/App.class 
	 */
	public static void loadClassPath(String classRootPath) {
		// 设置class文件所在根路径  
		// 例如/usr/java/classes下有一个test.App类，则/usr/java/classes即这个类的根路径，而.class文件的实际位置是/usr/java/classes/test/App.class  
		File clazzPath = new File(classRootPath);  
		  
		// 记录加载.class文件的数量  
		int clazzCount = 0;  
		  
		if (clazzPath.exists() && clazzPath.isDirectory()) {  
		    // 获取路径长度  
		    int clazzPathLen = clazzPath.getAbsolutePath().length() + 1;  
		  
		    Stack<File> stack = new Stack<File>();  
		    stack.push(clazzPath);  
		  
		    // 遍历类路径  
		    while (stack.isEmpty() == false) {  
		        File path = stack.pop();  
		        File[] classFiles = path.listFiles(new FileFilter() {  
		            public boolean accept(File pathname) {  
		                return pathname.isDirectory() || pathname.getName().endsWith(".class");  
		            }  
		        });  
		        for (File subFile : classFiles) {  
		            if (subFile.isDirectory()) {  
		                stack.push(subFile);  
		            } else {  
		                if (clazzCount++ == 0) {  
		                    Method method = null;
							try {
								method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
							} catch (Exception e) {
								LOGGER.error("getDeclaredMethod('addURL') exception: ", e);
							}  
							if (method != null) {
			                    boolean accessible = method.isAccessible();  
			                    try {  
			                        if (accessible == false) {  
			                            method.setAccessible(true);  
			                        }  
			                        // 设置类加载器  
			                        URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();  
			                        // 将当前类路径加入到类加载器中  
			                        method.invoke(classLoader, clazzPath.toURI().toURL());  
			                    } catch (Exception e) {
			                    	LOGGER.error("init classloader exception: ", e);
			                    } finally {  
			                        method.setAccessible(accessible);  
			                    }  
							}
		                }  
		                // 文件名称  
		                String className = subFile.getAbsolutePath();  
		                className = className.substring(clazzPathLen, className.length() - 6);  
		                className = className.replace(File.separatorChar, '.');  
		                // 加载Class类  
		                try {
							Class.forName(className);
						} catch (Exception e) {
							LOGGER.error("Class.forName(" + className + ") exception: ", e);
						}  
		                LOGGER.debug("读取应用程序类文件[class={}]", className);  
		            }  
		        }  
		    }  
		}  
	}
}
